// 计算文件的SHA1
#include <stdio.h>
#include <wchar.h>
#include <windows.h>

#define HOSTSDIR L"C:\\Windows\\System32\\drivers\\etc\\hosts"

char* ReadFileAll(wchar_t* fname) {
  HANDLE hFile = CreateFileW(fname, GENERIC_READ, FILE_SHARE_READ, NULL,
                             OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
  LARGE_INTEGER fileSize;
  GetFileSizeEx(hFile, &fileSize);
  DWORD len = fileSize.QuadPart;
  char* str = malloc(len + 1);
  DWORD dwRead;
  ReadFile(hFile, str, len, &dwRead, NULL);
  CloseHandle(hFile);
  str[len] = '\0';
  return str;
}

char* readfile(char* fname) {
  FILE* f = fopen(fname, "r");
  fseek(f, 0, SEEK_END);
  long len = ftell(f);
  rewind(f);
  char* str = malloc(len + 1);
  fread(str, 1, len, f);
  fclose(f);
  str[len] = '\0';
  return str;
}

wchar_t* u8_to_wchar(char* str) {
  int len = MultiByteToWideChar(CP_UTF8, 0, str, -1, 0, 0);
  wchar_t* outstr = malloc(len * sizeof(wchar_t));
  MultiByteToWideChar(CP_UTF8, 0, str, -1, outstr, len);
  free(str);
  return outstr;
}

wchar_t* ascii_to_wchar(char* str) {
  int len = strlen(str) + 1;
  wchar_t* out = calloc(len, sizeof(wchar_t));
  mbstowcs(out, str, len);
  return out;
}

char* hash_sha1(char* str, int islen) {
  HCRYPTPROV hProv = 0;
  HCRYPTHASH hHash = 0;
  CryptAcquireContextW(&hProv, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT);
  CryptCreateHash(hProv, CALG_SHA1, 0, 0, &hHash);
  if (!islen) islen = strlen(str);
  CryptHashData(hHash, str, islen, 0);
  DWORD outlen = 20;
  BYTE outhash[20] = {0};
  CryptGetHashParam(hHash, HP_HASHVAL, outhash, &outlen, 0);
  CryptDestroyHash(hHash);
  CryptReleaseContext(hProv, 0);
  char* strhash = malloc(41);
  char hex[] = "0123456789abcdef";
  for (int i = 0; i < 20; i++) {
    strhash[i * 2] = hex[outhash[i] >> 4];
    strhash[i * 2 + 1] = hex[outhash[i] & 0xf];
  }
  strhash[40] = '\0';
  return strhash;
}

char* git_sha1(char* str) {
  int islen = strlen(str);
  int i = 0;
  for (int l = islen; l; l = l / 10, i++)
    ;
  int gslen = islen + 6 + i;
  char* gitstr = malloc(gslen + 1);
  sprintf(gitstr, "blob %d0%s", islen, str);
  gitstr[5 + i] = '\0';
  char* outstr = hash_sha1(gitstr, gslen);
  free(gitstr);
  return outstr;
}

int wmain(int argc, wchar_t** argv) {
  char* str = ReadFileAll(HOSTSDIR);
  char* gitstr = git_sha1(str);
  printf("%s", gitstr);
  free(str);
  free(gitstr);
  return 0;
}